package org.liveboardgames.agricola.control.delegates.action
{

	import com.adobe.cairngorm.business.ServiceLocator;
	import com.adobe.cairngorm.control.CairngormEventDispatcher;
	
	import mx.rpc.IResponder;
	
	import org.liveboardgames.agricola.control.delegates.action.overrideaction.ActionOverrider;
	import org.liveboardgames.agricola.control.delegates.action.processor.ActionProcessor;
	import org.liveboardgames.agricola.control.delegates.action.processor.ActionProcessorFactory;
	import org.liveboardgames.agricola.control.events.RemoveResourceEvent;
	import org.liveboardgames.agricola.control.events.ResourceEvent;
	import org.liveboardgames.agricola.control.events.intern.ActionEvent;
	import org.liveboardgames.agricola.model.AgricolaModelLocator;
	import org.liveboardgames.agricola.vo.Game;
	import org.liveboardgames.agricola.vo.action.Action;
	import org.liveboardgames.agricola.vo.board.BoardTile;
	import org.liveboardgames.agricola.vo.card.Card;
	import org.liveboardgames.agricola.vo.common.Target;
	import org.liveboardgames.agricola.vo.player.Player;

	public class PerformActionDelegate
	{
		public var action:Action;

		public var game:Game;

		private var _responder:IResponder;

		private var _service:Object;

		public function PerformActionDelegate(responder:IResponder)
		{
			this._service = ServiceLocator.getInstance().getRemoteObject("actionService");
			this._responder = responder;
		}

		/**
		 * Execute the action passed as parameters. It can
		 * (and most often than not does) have an effet on
		 * the current game, that will be updated accordingly.
		 * There are two types of actions:
		 * <ul>
		 * <li>The ones that resolve themselves automatically,
		 * without any need for the player to choose anything
		 * <li>The ones that offer someone (usually the player
		 * who has just triggered the action) the possibility to
		 * choose the outcome.
		 * </ul>
		 * In the former case, the game is simply updated with
		 * the output of the action.
		 * In the latter, something should be activated in the
		 * graphical interface to offer the choice to the user.
		 */
		public function executeAction(target:Target = null):void
		{
			if (action.needPlayerInput)
			{
				// Pay the cost
				// TODO: if need a player input, the cost should be paid when the player
				// validates, so nothing to pay beforehand I guess
//				if (action.cost != null && action.cost.getKeys().length > 0 && (target is Player))
//				{
//					var event:ResourceEvent = new RemoveResourceEvent(RemoveResourceEvent.REMOVE_RESOURCE);
//					event.resourceHost = Player(target).farm;
//					event.resources = action.cost;
//					CairngormEventDispatcher.getInstance().dispatchEvent(event);
//				}
				performAction(target);
			}
			else
			{
				var type:String = null;
				var id:int = 0;
				if (target != null)
				{
					if (target is BoardTile)
					{
						type = "BoardTile";
						id = BoardTile(target).uniqueId;
					}
					else if (target is Card)
					{
						type = "Card";
						id = Card(target).cardId;
					}
					else if (target is Player)
					{
						type = "Player";
						id = Player(target).id;
					}
				}
				var call:Object = _service.executeAction(game.id, action.id, id, type);
				call.resultHandler = _responder.result;
				call.faultHandler = _responder.fault;
			}
		}

		private function performAction(target:Target = null):void
		{
			// Override the action depending on who performs it (for instance when the 
			// player has dedicated bonii on one action)
			var overriddenAction:Action = new ActionOverrider().overrideAction(action, target);

			var outputType:String = overriddenAction.actionOutput;

			var outputQuantity:int = action.outputQuantity;

			// Now we have everything we need to execute the 
			// minimal part of the action
			// We retrieve the class that will proces this
			var actionProcessor:ActionProcessor = ActionProcessorFactory.getProcessor(outputType, outputQuantity, overriddenAction);
			// Asynchronous response, since we want to make sure the action is really complete 
			// (e.g. when waiting for user input) before validating it
			actionProcessor.addEventListener(ActionEvent.ACTION_COMPLETE, onActionComplete);

			// Part where the action is really executed
			AgricolaModelLocator.getInstance().popups.currentAction = action;
			actionProcessor.execute();
		}

		private function onActionComplete(event:ActionEvent):void
		{
			// Return the original action, since the overridden one was used only 
			// internally
			_responder.result(action);
		}
	}
}